package com.kexio.user.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.kexio.user.entity.Permission;

/**
 * 权限数据访问层
 * 
 * 基于MyBatis Plus的权限数据访问接口，提供：
 * - 基础CRUD操作（继承自BaseMapper）
 * - 权限树形结构查询
 * - 权限关联查询
 * - 权限继承关系处理
 * - 多租户数据隔离
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@Mapper
public interface PermissionMapper extends BaseMapper<Permission> {
    
    // ==================== 基础查询 ====================
    
    /**
     * 根据权限编码和租户ID查询权限
     * 
     * @param permissionCode 权限编码
     * @param tenantId 租户ID
     * @return 权限信息
     */
    Permission selectByCodeAndTenant(@Param("permissionCode") String permissionCode);
    
    /**
     * 查询租户下的所有权限
     * 
     * @param tenantId 租户ID
     * @return 权限列表
     */
    List<Permission> selectByTenant();
    
    /**
     * 根据权限类型查询权限列表
     * 
     * @param permissionType 权限类型
     * @param tenantId 租户ID
     * @return 权限列表
     */
    List<Permission> selectByType(@Param("permissionType") String permissionType);
    
    // ==================== 角色关联查询 ====================
    
    /**
     * 查询角色拥有的权限列表
     * 
     * @param roleId 角色ID
     * @param tenantId 租户ID
     * @return 权限列表
     */
    List<Permission> selectByRole(@Param("roleId") String roleId);
    
    /**
     * 查询拥有指定权限的角色列表
     * 
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 角色列表
     */
    List<com.kexio.user.entity.Role> selectPermissionRoles(@Param("permissionId") String permissionId);
    
    // ==================== 用户关联查询 ====================
    
    /**
     * 查询用户拥有的权限列表（通过角色关联）
     * 
     * @param userId 用户ID
     * @param tenantId 租户ID
     * @return 权限列表
     */
    List<Permission> selectByUser(@Param("userId") String userId);
    
    /**
     * 查询用户拥有的权限编码列表
     * 
     * @param userId 用户ID
     * @param tenantId 租户ID
     * @return 权限编码列表
     */
    List<String> selectUserPermissionCodes(@Param("userId") String userId);
    
    /**
     * 查询租户下所有权限编码列表（用于超级管理员）
     * 
     * @param tenantId 租户ID
     * @return 所有权限编码列表
     */
    List<String> selectAllPermissionCodes();
    
    /**
     * 查询拥有指定权限的用户列表
     * 
     * @param permissionCode 权限编码
     * @param tenantId 租户ID
     * @return 用户列表
     */
    List<com.kexio.user.entity.User> selectPermissionUsers(@Param("permissionCode") String permissionCode);
    
    // ==================== 菜单关联查询 ====================
    
    /**
     * 查询菜单关联的权限列表
     * 
     * @param menuId 菜单ID
     * @param tenantId 租户ID
     * @return 权限列表
     */
    List<Permission> selectByMenu(@Param("menuId") Long menuId);
    
    /**
     * 查询权限关联的菜单列表
     * 
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 菜单列表
     */
    List<com.kexio.user.entity.Menu> selectPermissionMenus(@Param("permissionId") String permissionId);
    
    // ==================== 权限层级查询 ====================
    
    /**
     * 查询权限的直接子权限
     * 
     * @param parentPermissionId 父权限ID
     * @param tenantId 租户ID
     * @return 子权限列表
     */
    List<Permission> selectChildPermissions(@Param("parentPermissionId") Long parentPermissionId);
    
    /**
     * 查询权限的所有祖先权限（向上查询）
     * 
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 祖先权限列表
     */
    List<Permission> selectAncestorPermissions(@Param("permissionId") String permissionId);
    
    /**
     * 查询权限的所有后代权限（向下查询）
     * 
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 后代权限列表
     */
    List<Permission> selectDescendantPermissions(@Param("permissionId") String permissionId);
    
    /**
     * 查询根权限列表（没有父权限的权限）
     * 
     * @param tenantId 租户ID
     * @return 根权限列表
     */
    List<Permission> selectRootPermissions();
    
    // ==================== 权限检查 ====================
    
    /**
     * 检查权限编码是否存在
     * 
     * @param permissionCode 权限编码
     * @param tenantId 租户ID
     * @return 是否存在
     */
    default boolean existsByCode(@Param("permissionCode") String permissionCode) {
        LambdaQueryWrapper<Permission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Permission::getCode, permissionCode);
        return this.selectCount(wrapper) > 0;
    }
    
    /**
     * 检查用户是否拥有指定权限
     * 
     * @param userId 用户ID
     * @param permissionCode 权限编码
     * @param tenantId 租户ID
     * @return 是否拥有权限
     */
    boolean hasPermission(@Param("userId") String userId, @Param("permissionCode") String permissionCode);
    
    /**
     * 检查用户是否拥有任一权限
     * 
     * @param userId 用户ID
     * @param permissionCodes 权限编码列表
     * @param tenantId 租户ID
     * @return 是否拥有任一权限
     */
    boolean hasAnyPermission(@Param("userId") String userId, @Param("permissionCodes") List<String> permissionCodes);
    
    // ==================== 统计查询 ====================
    
    /**
     * 统计租户权限总数
     * 
     * @param tenantId 租户ID
     * @return 权限总数
     */
    default Long countPermissionsByTenant() {
        LambdaQueryWrapper<Permission> wrapper = new LambdaQueryWrapper<>();
        return this.selectCount(wrapper);
    }
    
    /**
     * 统计启用的权限数量
     * 
     * @param tenantId 租户ID
     * @return 启用权限数
     */
    default Long countActivePermissions() {
        LambdaQueryWrapper<Permission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Permission::getStatus, 1);
        return this.selectCount(wrapper);
    }
    
    /**
     * 统计各类型权限数量
     * 
     * @param tenantId 租户ID
     * @return 类型统计结果 Map<权限类型, 数量>
     */
    List<java.util.Map<String, Object>> countPermissionsByType();
    
    // ==================== 状态查询 ====================
    
    /**
     * 查询启用状态的权限列表
     * 
     * @param tenantId 租户ID
     * @return 启用权限列表
     */
    List<Permission> selectActivePermissions();
    
    /**
     * 查询指定状态的权限列表
     * 
     * @param status 权限状态
     * @param tenantId 租户ID
     * @return 权限列表
     */
    List<Permission> selectPermissionsByStatus(@Param("status") String status);
    
    // ==================== 缓存相关 ====================
    
    /**
     * 查询权限的最后更新时间（用于缓存失效判断）
     * 
     * @param permissionId 权限ID
     * @param tenantId 租户ID
     * @return 最后更新时间
     */
    default java.time.LocalDateTime selectLastUpdateTime(@Param("permissionId") String permissionId) {
        LambdaQueryWrapper<Permission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Permission::getId, permissionId)
               .select(Permission::getUpdateTime);
        Permission p = this.selectOne(wrapper);
        return p != null ? p.getUpdateTime() : null;
    }
}
